Skip to content

Add APNG Studio canvas extension#2272

Open
AndreaGriffiths11 wants to merge 7 commits into
github:mainfrom
AndreaGriffiths11:add-apng-studio-canvas
Open

Add APNG Studio canvas extension#2272
AndreaGriffiths11 wants to merge 7 commits into
github:mainfrom
AndreaGriffiths11:add-apng-studio-canvas

Conversation

@AndreaGriffiths11

Copy link
Copy Markdown
Contributor

Description

APNG Studio is an interactive GitHub Copilot canvas extension for building Animated PNG (APNG) files from frames. It renders in a side panel and is also driveable through agent actions.

Features:

  • Draw frames on a built-in canvas (pen/eraser, fill, onion-skin) or upload images.
  • Per-frame timing as an exact numerator/denominator fraction, plus per-frame dispose_op and blend_op from the APNG spec.
  • Loop count and an optional hidden first frame (static fallback for non-APNG viewers).
  • Live preview, and a "Send to phone" QR that serves the animation over the LAN from a short-lived, token-gated endpoint.
  • Export a valid animated .png (byte-compatible with PNG, so every viewer can open it).

The APNG codec and a dependency-free QR encoder are vendored (apng.mjs, qr.mjs); no third-party runtime dependencies.

Contribution type

Canvas extension, added at extensions/apng-studio/ with .github/plugin/plugin.json and assets/preview.png.

Validation

  • npm run plugin:validate: extension apng-studio is valid.
  • npm start: regenerated .github/plugin/marketplace.json; README requires no changes.

APNG Studio is an interactive GitHub Copilot canvas extension for building
Animated PNG (APNG) files from frames: draw or upload frames, tune per-frame
timing and compositing, preview live, send the result to a phone by QR, and
export an animated .png.

Adds extensions/apng-studio/ with the required .github/plugin/plugin.json and
assets/preview.png, and regenerates .github/plugin/marketplace.json.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 11, 2026 11:20
@github-actions github-actions Bot added canvas-extension PR touches canvas extensions new-submission PR adds at least one new contribution labels Jul 11, 2026
@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🔴 Contributor Reputation Check: HIGH risk

Check Risk
Profile HIGH
Credential audit NONE

Maintainers: please review this contributor before merging.
See the workflow run for full details.
Automated check powered by AGT.

@github-actions github-actions Bot added the needs-review:HIGH Contributor reputation check flagged HIGH risk label Jul 11, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds APNG Studio, a canvas extension for creating, previewing, sharing, and exporting animated PNGs.

Changes:

  • Adds APNG and QR encoders with persistent project storage.
  • Adds the interactive canvas UI and agent actions.
  • Registers the extension in the marketplace.
Show a summary per file
File Description
.github/plugin/marketplace.json Registers APNG Studio.
extensions/apng-studio/.github/plugin/plugin.json Defines extension metadata.
extensions/apng-studio/LICENSE Adds the MIT license.
extensions/apng-studio/README.md Documents features and installation.
extensions/apng-studio/apng.mjs Implements PNG/APNG encoding.
extensions/apng-studio/assets/demo.png Provides the README demonstration.
extensions/apng-studio/assets/preview.png Provides the marketplace preview.
extensions/apng-studio/copilot-extension.json Defines runtime metadata.
extensions/apng-studio/extension.mjs Implements storage, actions, servers, and sharing.
extensions/apng-studio/qr.mjs Implements QR encoding.
extensions/apng-studio/web/app.js Implements client-side behavior.
extensions/apng-studio/web/index.html Defines the canvas interface.
extensions/apng-studio/web/styles.css Styles the canvas interface.

Review details

  • Files reviewed: 11/13 changed files
  • Comments generated: 9
  • Review effort level: Medium

Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/README.md Outdated
Comment thread extensions/apng-studio/README.md
Comment thread extensions/apng-studio/web/index.html Outdated
Comment thread extensions/apng-studio/web/index.html Outdated
Security and robustness (extension.mjs):
- Reject "." and ".." project ids so canvas/action input cannot resolve
  outside artifacts/.
- Bound request bodies (1 MiB JSON, 40 MiB frame upload); return 413 when
  exceeded.
- Reject malformed JSON with 400 instead of coercing to {}, so a truncated
  body cannot trigger destructive routes such as /frames/clear.
- Scope shares per project so one canvas cannot rotate or stop another's
  share; the LAN server is shared and torn down once no shares remain.
- get_state treats hiddenFirst as active only with >=2 frames, matching the
  encoder, so a single-frame project reports the correct duration.

Accessibility (web/):
- Expose Pen/Eraser state with aria-pressed and keep it in sync in setTool.
- Mark the toast as an aria-live status region.

Packaging:
- Add extensions/apng-studio/.gitignore with artifacts/ so the documented
  runtime-data exclusion holds for this extension.
- Update the README install section to reference the committed awesome-copilot
  extension path.

Regenerated .github/plugin/marketplace.json.
Copilot AI review requested due to automatic review settings July 11, 2026 11:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 12/14 changed files
  • Comments generated: 10
  • Review effort level: Medium

Comment thread extensions/apng-studio/qr.mjs
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/web/app.js Outdated
Comment thread extensions/apng-studio/web/app.js
Comment thread extensions/apng-studio/web/index.html Outdated
Comment thread extensions/apng-studio/web/index.html Outdated
Comment thread extensions/apng-studio/web/index.html Outdated
Comment thread extensions/apng-studio/web/index.html Outdated
Update the plugin description (and regenerated marketplace entry) to refer to
the host as the GitHub Copilot app.
Copilot AI review requested due to automatic review settings July 11, 2026 12:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 12/14 changed files
  • Comments generated: 8
  • Review effort level: Medium

Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/web/index.html Outdated
Comment thread extensions/apng-studio/web/index.html Outdated
Comment thread extensions/apng-studio/web/index.html Outdated
Comment thread extensions/apng-studio/web/index.html Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
Security:
- Require a per-server access token on every loopback data/mutation request
  (minted per canvas server, carried in the iframe URL, attached to every
  renderer request). Static assets stay public. Blocks a local process or
  cross-origin page from reading state or driving mutations.

Concurrency and durability:
- Serialize the load-mutate-save cycle per project; dedupe concurrent first
  loads; write project.json via temp file + rename.

Lifecycle:
- Track SSE clients per instance and end them before server.close().
- Stop a project's LAN share only when no other panel references it.

Correctness:
- Report exact numerator/denominator total duration; handle pointercancel.

QR and accessibility:
- Place QR version bits least-significant-bit first (versions 7-10).
- Associate delay/fps/dispose/blend labels with their inputs via for=.
Copilot AI review requested due to automatic review settings July 11, 2026 12:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 12/14 changed files
  • Comments generated: 6
  • Review effort level: Medium

Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/web/app.js Outdated
Comment thread extensions/apng-studio/web/app.js Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
- Run assemble() under the project lock; add_color_frame renders and appends
  within one lock.
- Validate uploaded frames (PNG chunk scan, size + dimension checks) before
  writing; first frame stores real dimensions; CanvasError maps to 400.
- Validate move delta; clear frames in memory before deleting files.
- Route the open-handler rename through applySettings.
- Deduplicate LAN share startup; clean up if the canvas closes mid-start.
- End SSE streams before server.close(); skip dead streams in broadcast.
- Exact fractional duration; drawing surface stays >= 1px; refresh state before
  re-seeding "start from last frame".
Copilot AI review requested due to automatic review settings July 11, 2026 13:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 12/14 changed files
  • Comments generated: 6
  • Review effort level: Medium

Comment thread extensions/apng-studio/extension.mjs
Comment thread extensions/apng-studio/web/index.html Outdated
Comment thread extensions/apng-studio/web/app.js Outdated
Comment thread extensions/apng-studio/extension.mjs
Comment thread extensions/apng-studio/extension.mjs
Comment thread extensions/apng-studio/extension.mjs
- Validate uploaded frames are 8-bit RGBA non-interlaced PNGs (standard
  compression/filter); reject formats the codec can't encode.
- Cap projects at 600 frames (add + duplicate).
- Bind the LAN share server to the private address, not 0.0.0.0; require a
  private address and rebind when it changes while idle; build the URL from the
  bound address.
- Align width/height inputs and clampSize to the 2048 maximum.
- Size the drawing surface by width + aspect ratio for narrow panels.
- set_frame with an unknown frameId returns a validation error.
Copilot AI review requested due to automatic review settings July 11, 2026 13:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 12/14 changed files
  • Comments generated: 7
  • Review effort level: Medium

Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs
Comment thread extensions/apng-studio/extension.mjs Outdated
Comment thread extensions/apng-studio/extension.mjs Outdated
- 256 MiB aggregate encoded-byte budget (add + duplicate); per-frame size
  tracked and backfilled on load, so a frame count alone no longer bounds
  assembly memory.
- Frame timing is one exclusive mode (delayMs | fps | delayNum/delayDen);
  combinations are rejected instead of producing hybrid delays.
- Collision-resistant project storage keys: safe ids are used verbatim (existing
  projects still load) and only unsafe ids get a hash suffix, so "foo/bar" and
  "foo?bar" can't share a directory.
- Load only treats a missing file as a new project; other read/parse errors
  surface instead of silently overwriting real data.
- Share server binds to a real LAN interface (skips virtual/VPN/container,
  prefers physical NICs and common ranges).
- Generated export names get millisecond + random suffix to avoid same-second
  overwrite.
- PNG validator accepts the encoder's Uint8Array so agent solid-color frames
  aren't rejected.
Copilot AI review requested due to automatic review settings July 11, 2026 13:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 12/14 changed files
  • Comments generated: 5
  • Review effort level: Medium

Comment on lines +318 to +321
meta.frames.splice(i, 1);
await fs.rm(framePath(meta.id, fid), { force: true });
await saveProject(meta);
broadcast(meta.id);
Comment on lines +1162 to +1164
entry = { instanceId: ctx.instanceId, projectId, sse: new Set() };
servers.set(ctx.instanceId, entry);
await startServer(entry);
Comment on lines +180 to +185
return {
delayNum,
delayDen,
disposeOp: clampOp(f.disposeOp, 2),
blendOp: clampOp(f.blendOp, 1),
};
Comment on lines +443 to +445
const first = await createImageBitmap(files[0]);
const { w, h } = clampSize(first.width, first.height);
await api("/settings", { width: w, height: h });
Comment on lines +456 to +460
const bmp = await createImageBitmap(file);
const c = document.createElement("canvas");
c.width = state.width;
c.height = state.height;
drawContain(c.getContext("2d"), bmp, state.width, state.height);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

canvas-extension PR touches canvas extensions needs-review:HIGH Contributor reputation check flagged HIGH risk new-submission PR adds at least one new contribution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants